package com.example.scenictourback.service.impl;

import com.example.scenictourback.dto.OrderDTO;
import com.example.scenictourback.entity.Order;
import com.example.scenictourback.entity.Room;
import com.example.scenictourback.entity.Ticket;
import com.example.scenictourback.entity.User;
import com.example.scenictourback.repository.OrderRepository;
import com.example.scenictourback.repository.RoomRepository;
import com.example.scenictourback.repository.TicketRepository;
import com.example.scenictourback.repository.UserRepository;
import com.example.scenictourback.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityNotFoundException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private TicketRepository ticketRepository;
    
    @Autowired
    private RoomRepository roomRepository;

    @Override
    public List<OrderDTO> listAllOrders(Integer type, Integer status) {
        List<Order> orders;
        if (type != null && status != null) {
            orders = orderRepository.findAll().stream()
                    .filter(order -> order.getType().equals(type) && order.getStatus().equals(status))
                    .collect(Collectors.toList());
        } else if (type != null) {
            orders = orderRepository.findAll().stream()
                    .filter(order -> order.getType().equals(type))
                    .collect(Collectors.toList());
        } else if (status != null) {
            orders = orderRepository.findAll().stream()
                    .filter(order -> order.getStatus().equals(status))
                    .collect(Collectors.toList());
        } else {
            orders = orderRepository.findAll();
        }
        
        List<OrderDTO> orderDTOs = orders.stream()
                .map(order -> {
                    OrderDTO dto = OrderDTO.fromEntity(order);
                    setProductName(dto);
                    return dto;
                })
                .collect(Collectors.toList());
        
        return orderDTOs;
    }

    @Override
    public List<OrderDTO> listUserOrders(Integer userId, Integer type, Integer status) {
        List<Order> orders = orderRepository.findByUserId(userId);
        
        if (type != null) {
            orders = orders.stream()
                    .filter(order -> order.getType().equals(type))
                    .collect(Collectors.toList());
        }
        
        if (status != null) {
            orders = orders.stream()
                    .filter(order -> order.getStatus().equals(status))
                    .collect(Collectors.toList());
        }
        
        List<OrderDTO> orderDTOs = orders.stream()
                .map(order -> {
                    OrderDTO dto = OrderDTO.fromEntity(order);
                    setProductName(dto);
                    return dto;
                })
                .collect(Collectors.toList());
        
        return orderDTOs;
    }

    @Override
    public OrderDTO getOrderByOrderNo(String orderNo) {
        Order order = orderRepository.findByOrderNo(orderNo)
                .orElseThrow(() -> new EntityNotFoundException("订单不存在"));
        
        OrderDTO orderDTO = OrderDTO.fromEntity(order);
        setProductName(orderDTO);
        
        return orderDTO;
    }

    @Override
    public OrderDTO getOrderById(Integer id) {
        Order order = orderRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("订单不存在"));
        
        OrderDTO orderDTO = OrderDTO.fromEntity(order);
        setProductName(orderDTO);
        
        return orderDTO;
    }

    @Override
    @Transactional
    public OrderDTO createOrder(Order order) {
        // 生成订单号
        String orderNo = generateOrderNo();
        order.setOrderNo(orderNo);
        
        // 设置订单用户
        User user = userRepository.findById(order.getUser().getId())
                .orElseThrow(() -> new EntityNotFoundException("用户不存在"));
        order.setUser(user);
        
        // 设置下单日期
        order.setBookDate(new Date());
        
        // 保存订单
        Order savedOrder = orderRepository.save(order);
        
        // 如果是酒店订单，更新房间可用数量
        if (order.getType() == 2) {
            Room room = roomRepository.findById(order.getProductId())
                    .orElseThrow(() -> new EntityNotFoundException("房间不存在"));
            
            int availableRooms = room.getAvailable() - order.getQuantity();
            if (availableRooms < 0) {
                throw new IllegalStateException("房间数量不足");
            }
            
            room.setAvailable(availableRooms);
            roomRepository.save(room);
        }
        
        OrderDTO orderDTO = OrderDTO.fromEntity(savedOrder);
        setProductName(orderDTO);
        
        return orderDTO;
    }

    @Override
    @Transactional
    public OrderDTO updateOrderStatus(Integer id, Integer status) {
        Order order = orderRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("订单不存在"));
        
        // 更新状态
        order.setStatus(status);
        Order updatedOrder = orderRepository.save(order);
        
        OrderDTO orderDTO = OrderDTO.fromEntity(updatedOrder);
        setProductName(orderDTO);
        
        return orderDTO;
    }

    @Override
    @Transactional
    public OrderDTO cancelOrder(Integer id) {
        Order order = orderRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("订单不存在"));
        
        // 只有待支付和已支付的订单可以取消
        if (order.getStatus() != 1 && order.getStatus() != 2) {
            throw new IllegalStateException("当前状态无法取消订单");
        }
        
        // 更新状态为已取消
        order.setStatus(4);
        Order canceledOrder = orderRepository.save(order);
        
        // 如果是酒店订单，返回房间库存
        if (order.getType() == 2) {
            Room room = roomRepository.findById(order.getProductId())
                    .orElseThrow(() -> new EntityNotFoundException("房间不存在"));
            
            room.setAvailable(room.getAvailable() + order.getQuantity());
            roomRepository.save(room);
        }
        
        OrderDTO orderDTO = OrderDTO.fromEntity(canceledOrder);
        setProductName(orderDTO);
        
        return orderDTO;
    }

    @Override
    @Transactional
    public void deleteOrder(Integer id) {
        Order order = orderRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("订单不存在"));
        
        // 只有已取消的订单可以删除
        if (order.getStatus() != 4) {
            throw new IllegalStateException("只有已取消的订单可以删除");
        }
        
        orderRepository.deleteById(id);
    }

    @Override
    public Map<String, Object> getOrderStats() {
        Map<String, Object> stats = new HashMap<>();
        List<Order> allOrders = orderRepository.findAll();
        
        // 订单总数
        stats.put("totalOrders", allOrders.size());
        
        // 订单状态统计
        Map<Integer, Long> statusStats = allOrders.stream()
                .collect(Collectors.groupingBy(Order::getStatus, Collectors.counting()));
        stats.put("statusStats", statusStats);
        
        // 订单类型统计
        Map<Integer, Long> typeStats = allOrders.stream()
                .collect(Collectors.groupingBy(Order::getType, Collectors.counting()));
        stats.put("typeStats", typeStats);
        
        // 总营收
        BigDecimal totalRevenue = allOrders.stream()
                .filter(order -> order.getStatus() == 2 || order.getStatus() == 3) // 已支付或已完成
                .map(Order::getTotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        stats.put("totalRevenue", totalRevenue);
        
        return stats;
    }
    
    // 设置产品名称
    private void setProductName(OrderDTO orderDTO) {
        if (orderDTO.getType() == 1) {
            // 门票
            ticketRepository.findById(orderDTO.getProductId()).ifPresent(ticket -> {
                orderDTO.setProductName(ticket.getName());
            });
        } else if (orderDTO.getType() == 2) {
            // 酒店房间
            roomRepository.findById(orderDTO.getProductId()).ifPresent(room -> {
                orderDTO.setProductName(room.getHotel().getName() + " - " + room.getType());
            });
        }
    }
    
    // 生成订单号
    private String generateOrderNo() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String dateStr = sdf.format(new Date());
        String randomStr = String.format("%04d", new Random().nextInt(10000));
        return dateStr + randomStr;
    }
} 